#pragma once
//#include <sigslot.h>
#include <3rdParty/boostsignal2.hpp>
#include "../VisionAlgo/EdgeTracer.hpp"
#include <Renderer/OneImageRenderer.hpp>
#include "CutGUI.hpp"
#include "BrushGUI.hpp"

// USAGE: to cut out a piece from a image with Intelligent Scissor
// call Prepare to init
// click will optimize inside a square
// use +/- to change the square's size
// if you do not want optimization, change the size to minimal
// left click to add fix point
// right click to delete last fix point
// when close to the first fix point, it will snap, click to close the loop

// press control to draw preferance region
// path will prefer to go inside preferance region
// left click to draw
// right click to erase
// use ctrl+ +/- to change the brush size

// hold shift to draw straight line, rather than trace edge

// wheel to zoom, middle button to move

// press Enter to finish, it will send a signal FinishCut(const Image4f &)
// paramenter is the cutout, if no cut, it will send the whole image


namespace zzz{
template<typename T>
class CutRenderer : public OneImageRenderer<T>
{
public:
  CutRenderer()
  {
    lock_=false;
    cutgui_.Init(this);
    brushgui_.Init(this);
    guitype_=GUICUT;
  }
  void OnMouseMove(unsigned int nFlags,int x,int y) 
  {
    OneImageRenderer::OnMouseMove(nFlags,x,y);
    if (guitype_==GUICUT)
      cutgui_.OnMouseMove(nFlags, x, y);
    else
      brushgui_.OnMouseMove(nFlags, x, y);
  }
  void OnLButtonDown(unsigned int nFlags,int x,int y)
  {
    if (lock_) return;
    if (guitype_==GUICUT)
      cutgui_.OnLButtonDown(nFlags, x, y);
    else
      brushgui_.OnLButtonDown(nFlags, x, y);
  }
  void OnLButtonUp(unsigned int nFlags,int x,int y)
  {
    if (lock_) return;
    if (guitype_==GUICUT)
      cutgui_.OnLButtonUp(nFlags, x, y);
    else
      brushgui_.OnLButtonUp(nFlags, x, y);
  }
  void OnRButtonDown(unsigned int nFlags,int x,int y)
  {
    if (lock_) return;
    if (guitype_==GUICUT)
      cutgui_.OnRButtonDown(nFlags, x, y);
    else
      brushgui_.OnRButtonDown(nFlags, x, y);
  }
  void OnRButtonUp(unsigned int nFlags,int x,int y)
  {
    if (lock_) return;
    if (guitype_==GUICUT)
      cutgui_.OnRButtonUp(nFlags, x, y);
    else
      brushgui_.OnRButtonUp(nFlags, x, y);
  }
  void OnKeyDown(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags)
  {
    if (lock_) return;
    if (nChar==ZZZKEY_SPACE) {
      if (guitype_==GUICUT) {
        brushgui_.mask_=cutgui_.segments_;
        guitype_=GUIBRUSH;
      } else {
        cutgui_.segments_=brushgui_.mask_;
        guitype_=GUICUT;
      }
      return;
    }

    if (guitype_==GUICUT)
      cutgui_.OnKeyDown(nChar, nRepCnt, nFlags);
    else
      brushgui_.OnKeyDown(nChar, nRepCnt, nFlags);
  }
  void OnKeyUp(unsigned int nChar, unsigned int nRepCnt, unsigned int nFlags)
  {
    if (lock_) return;
    if (guitype_==GUICUT)
      cutgui_.OnKeyUp(nChar, nRepCnt, nFlags);
    else
      brushgui_.OnKeyUp(nChar, nRepCnt, nFlags);
    if (Within<zuint>(ZZZKEY_0,nChar,ZZZKEY_9)) {
      cutgui_.curseg_=nChar-ZZZKEY_0;
      brushgui_.sel_id_=nChar-ZZZKEY_0;
    }
  }
  void Prepare(const Image<T> &img)
  {
    cutgui_.Prepare(img);
    brushgui_.Prepare(img);
  }

  const Imageuc& GetSegments() const
  {
    if (guitype_==GUICUT)
      return cutgui_.segments_;
    else
      return brushgui_.mask_;
  }

  void Lock(bool locked)
  {
    lock_=locked;
  }

  void DrawObj()
  {
    if (guitype_== GUICUT)
      DrawImage(cutgui_.show_);
    else
      DrawImage(brushgui_.show_);
  }
private:
  bool lock_;
  CutGUI cutgui_;
  BrushGUI brushgui_;
  enum GuiType {GUICUT, GUIBRUSH} guitype_;
};
}